package com.cyy.defstep;

import com.cyy.contanst.GlobalVar;
import com.cyy.service.AppiumService;
import com.cyy.utils.Common;
import com.cyy.utils.ElementBy;
import com.cyy.utils.YmlParser;
import io.appium.java_client.touch.offset.PointOption;
import io.cucumber.java.BeforeStep;
import io.cucumber.java.Scenario;
import io.cucumber.java.zh_cn.同时;
import io.cucumber.java.zh_cn.当;
import io.cucumber.java.zh_cn.那么;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringSubstitutor;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.springframework.beans.factory.annotation.Autowired;
import java.net.MalformedURLException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

@Slf4j
public class AndroidUIDefstep extends AbstractDefstep {
    @Autowired
    AppiumService appiumService;
    @Autowired
    Common common;

    String config_key = "android.ui.element.path.yaml";
    String series;

    @BeforeStep("@app")
    public void before_step_app(Scenario scenario) throws ParseException {
        if (series == null) return;
        String name = common.today("yyyyMMddhhmmss") + ".png";
        String remotepath = null;
        try {
            String path = common.get_project_path() + "/temp/" + name;
            Map<String, Object> screen = appiumService.screen(path, series);
            if (screen == null) return;
            remotepath = screen.get("remotepath").toString();
            scenario.attach((byte[]) screen.get("byte"), "image/png", "步骤截图");
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (remotepath != null) appiumService.rm_file(remotepath, series);
        }
    }

    @当("^【(.*?)】登录android系统,输入手机号(.*?)和验证码(.*?)$")
    public void login_app(String series, String telphone, String code) throws MalformedURLException {
        // 检查手机是否连接
        if (appiumService.is_advice_connected("android", series)) {
            boolean connected = false;
            for (int i = 0; i < 3; i++) {
                connected = appiumService.connect_advice("android", series);
                if (connected) break;
            }
            assertThat("设备" + series + "不能链接", connected);
        }


        // 判断手机是否为熄屏状态，如果是，打开手机
        appiumService.wake("android", series);

        appiumService.installDriver("android", series);
        appiumService.swipe_left(series);
        appiumService.swipe_left(series);
        appiumService.click(series, getAndroidBy("欢迎页.按钮立即体验"));
        appiumService.input(series, getAndroidBy("登录页.输入框手机号码"), telphone);
        appiumService.input(series, getAndroidBy("登录页.输入框验证码"), code);
        appiumService.click(series, getAndroidBy("登录页.按钮登录"));
        WebElement element = appiumService.find_element_by(series, getAndroidBy("首页.按钮下次再说"));
        if (element != null) {
            element.click();
        }

        // 如果首页显示开始接单，点击
        if (appiumService.find_element_by(series,getAndroidBy("首页.按钮开始接单"))!=null){
            appiumService.click(series,getAndroidBy("首页.按钮开始接单"));
        }
        // 检查是否登录成功
        check_is_home(series);
        this.series = series;

        // 获取设备的信息
        Map<String, String> infos = get_infos(series);
        GlobalVar.equipments.put(infos.get("name"), infos.get("value"));
    }

    @那么("^【(.*?)】检查android系统接收订单是否成功：发包方(.*?),车主车牌号(.*),车主信息包含(.*?)$")
    public void check_accept_order_is_success(String series, String fbf, String cph, String info) {
        assertThat("按钮拒绝接单不存在",
                appiumService.find_element_by(series, getAndroidBy("任务详情.按钮拒单")),
                notNullValue());
        assertThat("按钮我要抢单不存在",
                appiumService.find_element_by(series, getAndroidBy("任务详情.按钮我要抢单")),
                notNullValue());
        assertThat("期望发包方是" + fbf, appiumService.find_element_by(series,
                getAndroidBy("任务详情.对象发包方")).getText(),
                equalTo(fbf));
        assertThat("期望对象车主车牌号是" + cph, appiumService.find_element_by(series,
                getAndroidBy("任务详情.对象车主车牌号")).getText(),
                equalTo(cph));
        assertThat("期望对象车主信息包含" + cph, appiumService.find_element_by(series,
                getAndroidBy("任务详情.对象车主信息")).getText(),
                containsString(info));

    }

    @那么("^【(.*?)】android系统下拒单$")
    public void quit_order(String series) {
        appiumService.click(series, getAndroidBy("任务详情.按钮拒单"));
        appiumService.click(series, getAndroidBy("任务详情.按钮拒单弹出框确定"));
    }


    @那么("^【(.*?)】android系统下抢单$")
    public void get_order(String series) {
        appiumService.click(series, getAndroidBy("任务详情.按钮我要抢单"));
        appiumService.waituntil(series, 2000);
        appiumService.click_screen(series); // 点击屏幕
    }

    @那么("^【(.*?)】android系统下给车主打电话$")
    public void call(String series) {
        appiumService.click(series,getAndroidBy("请赶往现场.按钮电话"));
        appiumService.waituntil(series,2000);
        appiumService.cancel_call(series);
        appiumService.waituntil(series,5000);
        this.swipe_for_calltel(series);
        appiumService.click(series,getAndroidBy("请赶往现场.按钮滑动滑动条后弹出提示框下确定"));
        appiumService.waituntil(series,2000);
        appiumService.click_screen(series);
    }

    @那么("^【(.*?)】android系统下检查是否回到首页$")
    public void check_is_home(String series) {
        assertThat("对象停止接单按不存在", appiumService.find_element_by(series, getAndroidBy("首页.按钮等待派单")), notNullValue());
        assertThat("对象按钮停止接单不存在", appiumService.find_element_by(series, getAndroidBy("首页.按钮停止接单")), notNullValue());
    }

    @那么("^【(.*?)】android下退出小程序$")
    public void quit(String series) {
        appiumService.quit(series);
    }

    @那么("^【(.*?)】android下检查已结单页面信息:事发地为(.*?),距离现场约(.*?)公里,事故类型为(.*?).发包方为(.*?),事故车车牌号为(.*?),车主的信息包含(.*?)$")
    public void check_receiving_order_is_success(String series,String location, String distance, String type, String dataSource, String plateNumber, String ownerInfo){
        String acc_loc = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象始发地")).getText();
        assertThat(acc_loc,equalTo(location));

        // 连续检查5次，每次等待1s
//        int check_times = 5;
//        int sleep_time= 1000;
//        String acc_dis = "";
//        for (int i=0; i<check_times;i++) {
//            acc_dis = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象距离现场距离")).getText();
//            //距现场约：25公里
//            acc_dis = acc_dis.replace("距现场约：","").replace("公里","");
//            if (distance.equals(acc_dis)){
//                break;
//            }
//            appiumService.waituntil(series,sleep_time);
//        }

//        assertThat(acc_dis,equalTo(distance));

        String acc_type = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象事故类型")).getText();
        assertThat(acc_type,equalTo(type));

        String acc_dataSource = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象发包方")).getText();
        assertThat(acc_dataSource,equalTo(dataSource));

        String acc_platenumber = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象车牌号")).getText();
        assertThat(acc_platenumber, equalTo(plateNumber));

        String acc_ownerInfo = appiumService.find_element_by(series, getAndroidBy("请赶往现场.对象车主信息")).getText();
        assertThat(acc_ownerInfo, equalTo(ownerInfo));
    }

    @那么("^【(.*?)】android下任务执行页面下客户签名$")
    public void autograph_customer(String series) {
        appiumService.click(series,getAndroidBy("任务执行.对象电子签名客户"));
        appiumService.waituntil(series,1000);
        appiumService.swipe_around_circle(series,100);
        appiumService.click(series,getAndroidBy("任务执行.按钮签名确认签名"));
    }

    @同时("^【(.*?)】android下任务执行页面下服务员签名$")
    public void autograph_fwy(String series) {
        appiumService.click(series,getAndroidBy("任务执行.对象电子签名服务员"));
        appiumService.waituntil(series,1000);
        appiumService.swipe_around_circle(series,100);
        appiumService.click(series,getAndroidBy("任务执行.按钮签名确认签名"));
    }


    @那么("^$【(.*?)】android下点击页面(.*?)的(.*?)$")
    public void click_el(String series, String page, String name) {
        appiumService.click(series,getAndroidBy(String.format("%s.%s",page,name)));
    }

    @那么("^$【(.*?)】android下向页面(.*?)的(.*?)输入(.*?)$")
    public void send_message(String series, String page,String name,String msg) {
        appiumService.find_element_by(series,getAndroidBy(String.format("%s.%s",page,name)))
                .sendKeys(msg);
    }

    /**
     * 根据配置文件下的指定对象的名字，获取元素定位信息
     *
     * @param name yaml文件下定位信息路径 eg:欢迎页.输入框手机号码
     * @return 元素定位的方式
     */
    private By getAndroidBy(String name) {
        Map<String, Object> jsonmap = (Map<String, Object>) GlobalVar.value.get(config_key);
        Object valueByKey = YmlParser.getValueByKey(jsonmap, name);
        assertThat(jsonmap + "\t" + name, valueByKey, notNullValue());
        By by = ElementBy.getBy(valueByKey.toString());
        assertThat(valueByKey + "  对象为空?", by, notNullValue());
        log.info("操作对象:" + name + "》" + by);
        return by;
    }

    /**
     * 根据配置文件下的指定对象的名字，获取元素定位信息
     * @param name yaml文件下定位信息路径 eg:欢迎页.输入框手机号码
     * @param args 匹配 如果定位方式内容下包含 ${name}的值，则会把args下的key为name的值替换
     * @return 元素定位的方式
     */
    private By getAndroidBy(String name, Map<String, String> args) {
        Map<String, Object> jsonmap = (Map<String, Object>) GlobalVar.value.get(config_key);
        Object valueByKey = YmlParser.getValueByKey(jsonmap, name);
        assertThat(jsonmap + "\t" + name, valueByKey, notNullValue());
        String replace = new StringSubstitutor(args).replace(valueByKey);
        By by = ElementBy.getBy(replace);
        assertThat(valueByKey + "  对象为空?", by, notNullValue());
        log.info("操作对象:" + name + "》" + by);
        return by;
    }

    /**
     * 获取手机的相关参数
     *
     * @param series 手机的序列号
     * @return 设备的相关信息，格式: name: 设备名字, value:设备信息
     */
    private Map<String, String> get_infos(String series) {
        Map<String, String> result = new HashMap<>();
        String memory_total = appiumService.get_memory_total(series).replace("\n", "");
        String memory_free = appiumService.get_memory_free(series).replace("\n", "");
        String product_brand = appiumService.get_product_brand(series).replace("\n", "");
        String system_version = appiumService.get_system_version(series).replace("\n", "");
        result.put("name", product_brand);
        String infos = system_version +
                "\n" + String.format("memory  total:%s  free:%s", memory_total, memory_free);
        result.put("value", infos);
        return result;
    }

    /**
     * 已接单页面滑动条
     * @param series 设备的序列号
     */
    private void swipe_for_calltel(String series) {
        Map<String, Float> el_bounds = appiumService.get_el_bounds(series, getAndroidBy("请赶往现场.对象右滑动条"));
        log.warn("滑动条在设备下的位置: " + el_bounds);
        appiumService.swipe(series
                ,PointOption.point((int) (el_bounds.get("startX") + 2), (int) (el_bounds.get("startY") + 2))
                ,PointOption.point((int) (el_bounds.get("endX") - 2), (int) (el_bounds.get("endY") - 2))
                ,3000);
    }

}
